package com.alm.handle.service.impl;

import com.alibaba.fastjson.JSON;
import com.alm.common.config.RuoYiConfig;
import com.alm.common.core.redis.RedisCache;
import com.alm.common.utils.SecurityUtils;
import com.alm.entity.PasingByteModel;
import com.alm.handle.core.domain.entity.AlmImgAddress;
import com.alm.handle.core.domain.entity.SysAreaInfo;
import com.alm.handle.core.domain.entity.SysDevInfo;
import com.alm.handle.core.domain.entity.SysDevModel;
import com.alm.handle.core.domain.entity.rq.LableAddAndUpdateRq;
import com.alm.handle.core.domain.entity.rq.LableInfoRq;
import com.alm.handle.core.domain.entity.rq.RefreshImgRq;
import com.alm.handle.core.domain.entity.rs.LableInfoDataRs;
import com.alm.handle.mapper.AlmImgAddressMapper;
import com.alm.handle.mapper.SysAreaInfoMapper;
import com.alm.handle.mapper.SysDevInfoMapper;
import com.alm.handle.mapper.SysDevModelMapper;
import com.alm.handle.service.AlmLableService;
import com.alm.handle.service.ISysAreaInfoService;
import com.alm.handle.util.*;
import com.alm.util.ByteArrayUtil;
import com.alm.util.Misc;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.netty.buffer.ByteBuf;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.alm.common.utils.PageUtils.startPage;

@Service
public class AlmLableServiceImpl  implements AlmLableService {
    private static final Logger log = LoggerFactory.getLogger(AlmLableServiceImpl.class);
    @Value("${swagger.pathMapping}")
    private String pathMapping;
    @Resource
    private SysDevInfoMapper sysDevInfoMapper;
    @Resource
    private SysAreaInfoMapper areaInfoMapper;
    @Resource
    private AlmImgAddressMapper imgAddressMapper;
    @Autowired
    private ISysAreaInfoService areaInfoService;
    @Resource
    private SysDevModelMapper devModelMapper;
    @Autowired
    private RedisCache redisCache;


    @Override
    public List<SysDevInfo> queryByLable(LableInfoRq lableInfoRq) {
        QueryWrapper queryWrapper = new QueryWrapper();
        if (lableInfoRq.getAreaId() != null && lableInfoRq.getAreaId().trim().length()> 1) {
            queryWrapper.eq("menu_id", lableInfoRq.getAreaId());
            SysAreaInfo sysAreaInfo = areaInfoMapper.selectOne(queryWrapper);
            if (sysAreaInfo != null ) {
                areaInfoService.findAllChild(sysAreaInfo);
            }
            sysAreaInfo.setChildIds(lableInfoRq.getAreaId());
            lableInfoRq.setAreaId(sysAreaInfo.getChildIds());
        }else{
            lableInfoRq.setAreaId(null);
        }
        startPage();
        List<SysDevInfo> list = sysDevInfoMapper.queryByLabel(lableInfoRq);
        return list;
    }

    @Override
    public int insertLable(LableAddAndUpdateRq lableAddAndUpdateRq) {
        SysDevInfo sysDevInfo=new SysDevInfo();
        sysDevInfo.setDeviceId(lableAddAndUpdateRq.getDeviceId());
        sysDevInfo.setDevType(112);
        sysDevInfo.setDevName(lableAddAndUpdateRq.getDevName());
        sysDevInfo.setDevModelType(lableAddAndUpdateRq.getDevModelType());
        sysDevInfo.setSectionId(SecurityUtils.getDeptId() );
        sysDevInfo.setCustomerId(SecurityUtils.getUserId());
        sysDevInfo.setRegionId(lableAddAndUpdateRq.getRegionId());
        sysDevInfo.setAddTime(System.currentTimeMillis());
        sysDevInfo.setActTime(new Date());
        sysDevInfo.setRemark(lableAddAndUpdateRq.getRemark());
        return sysDevInfoMapper.insert(sysDevInfo);
    }

    @Override
    public SysDevInfo queryByLabelByid(Integer id) {
        return sysDevInfoMapper.queryByLabelByid(id);
    }

    @Override
    public int updateLable(LableAddAndUpdateRq lableAddAndUpdateRq) {
        SysDevInfo sysDevInfo=new SysDevInfo();
        sysDevInfo.setId(lableAddAndUpdateRq.getId());
        sysDevInfo.setDevName(lableAddAndUpdateRq.getDevName());
        sysDevInfo.setDevModelType(lableAddAndUpdateRq.getDevModelType());
        sysDevInfo.setRegionId(lableAddAndUpdateRq.getRegionId());
        sysDevInfo.setRemark(lableAddAndUpdateRq.getRemark());
        return sysDevInfoMapper.updateById(sysDevInfo);
    }

    @Override
    public int delLable(Integer id) {
        return sysDevInfoMapper.deleteById(id);
    }

    @Override
    public LableInfoDataRs queryImgInfoById(Integer id) {
        LableInfoDataRs lableInfoDataRs=sysDevInfoMapper.queryImgInfo(id);
        if(lableInfoDataRs!=null){
            lableInfoDataRs.setImgUrl(pathMapping+lableInfoDataRs.getImgUrl());
        }
        return lableInfoDataRs;
    }

    @Override
    public int setLableImg(String filePath, String devid) {
        AlmImgAddress address=new AlmImgAddress();
        address.setImgAddress(filePath);
        address.setDevId(devid);
        QueryWrapper queryWrapper=new QueryWrapper();
        queryWrapper.eq("dev_id",devid);
        AlmImgAddress imgAddress=imgAddressMapper.selectOne(queryWrapper);
        if(imgAddress!=null){
            String path=RuoYiConfig.getProfile();
            path=path+imgAddress.getImgAddress().replace("/profile","");
            new File(path).delete();
            return imgAddressMapper.updateById(address);
        }else{
            return  imgAddressMapper.insert(address);
        }
    }

    @Override
    public void deal_lable_status(PasingByteModel.Header data) {
        //透传的  数据 不管
        int start=6;
        if(data.getIntData().get(start)==0x10){
            start+=1;
            //获取到透传配置对象
            switch (data.getIntData().get(start)){
                case 0:
                    log.info("00 TAG 连接失败");

                    break;
                case 1:
                    log.info("01 TAG 连接成功");
                    break;
                case 2:
                    log.info("02 TAG 连接超时");
                    break;
            }

        }
    }

    @Override
    public void deal_lable_business(PasingByteModel.Header data) {
        String dataKey=SoketEleKey.GW_RE_LABLE_DATA+data.getDvcId();
        String status_key= SoketEleKey.LABLE_STATUS+data.getDvcId();
        String jindu_key= SoketEleKey.LABLE_RE_STATUS+data.getDvcId();
        int cn=Integer.parseInt(ByteUtils.arrayToString(data.getIntData(),7,9),16);
        int currentNumber = Integer.parseInt( ByteUtils.arrayToString(data.getIntData(),9,11),16);
        int sendStatus = data.getIntData().get(11);
        String re_img=SoketEleKey.RE_IMG+data.getDvcId();
        redisCache.setCacheObject(re_img, 1,5, TimeUnit.SECONDS);
        if(sendStatus==0x01){
            log.info("01 TAG 标签刷新, 数据包发送成功 " );
            if(redisCache.hasKey(dataKey)){
                String img_data=redisCache.getCacheObject(dataKey);
                List<String> img_data_list=JSON.parseArray(img_data, String.class);
                BigDecimal jindu=new BigDecimal(currentNumber).
                        divide(new BigDecimal(img_data_list.size()),4,BigDecimal.ROUND_DOWN).
                        multiply(new BigDecimal(100)).
                        setScale(4,4);
                redisCache.setCacheObject(jindu_key,jindu,120, TimeUnit.SECONDS);
                if(currentNumber<img_data_list.size()){
                    byte[] configData= ByteUtils.hexStrToBytes(img_data_list.get(currentNumber));
                    byte[] after= InstructionByteUtils.getBYTEISData(0x5743
                            ,0x70,0x90,
                            configData,0x00);
                    ByteBuf befor= InstructionByteUtils.getBFBYTEInstruction(data.getDvcId(),
                            (short) 128,(short)0);
                    byte [] inBytes= InstructionByteUtils.getBYTEISBYTES(befor,after);

                    SendMessage.sendMessage(inBytes,data.getDvcId());
                }
            }
        } else if(LableErrerUtil.isErrer(sendStatus)){
            String errerMsg=LableErrerUtil.getErrer(sendStatus);
            log.info("标签刷新 {}",errerMsg);
            redisCache.setCacheObject(status_key,errerMsg,120, TimeUnit.SECONDS);
            redisCache.deleteObject(dataKey);
        }else{
            log.info("标签刷新 未知错误");
            redisCache.setCacheObject(status_key,"未知错误！",120, TimeUnit.SECONDS);
            redisCache.deleteObject(dataKey);
        }

    }
    @Override
    public Boolean refreshImg(RefreshImgRq refreshImgRq) throws Exception{
        SysDevModel sysDevModel=devModelMapper.selectById(refreshImgRq.getModelType());
        if(sysDevModel!=null){
            if(sysDevModel.getTagImageHeight()==null||sysDevModel.getTagImageWidth()==null){
                throw  new Exception("该标签型号图宽未设置！");
            }
            String path=RuoYiConfig.getProfile();
            QueryWrapper queryWrapper=new QueryWrapper();
            queryWrapper.eq("dev_id",refreshImgRq.getDevid());
            AlmImgAddress imgAddress= imgAddressMapper.selectOne(queryWrapper);
            if(imgAddress==null||imgAddress.getImgAddress()==null){
                throw  new Exception("未上传该标签的图片！");
            }
            path=path+imgAddress.getImgAddress().replace("/profile","");;
            if(refreshImgRq.getImgType().equals("01")){
                //判断图片宽高是否等于
                if(ImageUtil.isCheckWH(path,sysDevModel.getTagImageWidth(),sysDevModel.getTagImageHeight())){
                    throw  new Exception("图片规格不符合！");
                }
            }
            String imageLayer= ImageUtil.getImagePixel( path,
                    refreshImgRq.getLayerNumber(),true);
            String tagServerUUID = "0000";//标签服务id
            String tagCharUUID = "0000";//标签端口号id
            int onePack = 400;//拆分图片字节流, 单包字符最大长度
            ArrayList<String> imageDataList = getImgData(imageLayer,onePack);
            int totalSize = imageDataList.size();
            // 总包数
            String totalNumber =convertDecimalToHexadecimal(totalSize,4);
            // 具体包数名称
            String currentNumber;
            List<String> respList = new ArrayList<>();
            for(int i = 0; i < imageDataList.size(); i++)
            {
                currentNumber = convertDecimalToHexadecimal(i+1,4);
                //logger.info("totalNumber:{}, currentNumber:{}", totalNumber, currentNumber);
                //第一包指令下的数据包（只含颜色层数据），第二包及以后数据包（不含图片详情，只含图片数据）
                if(i == 0){
                    String colorLayer_01 = imageDataList.get(0);
                    StringBuffer tagPackData_01=new StringBuffer();
                    tagPackData_01.append(totalNumber);
                    tagPackData_01.append(currentNumber);
                    tagPackData_01.append(refreshImgRq.getDevid());
                    tagPackData_01.append(tagServerUUID);
                    tagPackData_01.append(tagCharUUID);
                    StringBuffer imgPackData_01=new StringBuffer();
                    imgPackData_01.append(refreshImgRq.getImgType());
                    imgPackData_01.append(refreshImgRq.getImgNo());
                    imgPackData_01.append(convertDecimalToHexadecimal(refreshImgRq.getSizeType(),2));
                    imgPackData_01.append(convertDecimalToHexadecimal(refreshImgRq.getSkewX(),4));
                    imgPackData_01.append(convertDecimalToHexadecimal(refreshImgRq.getSkewY(),4) );
                    imgPackData_01.append(convertDecimalToHexadecimal(sysDevModel.getTagImageWidth(),4));
                    imgPackData_01.append(convertDecimalToHexadecimal(sysDevModel.getTagImageHeight(),4));
                    imgPackData_01.append(convertDecimalToHexadecimal(refreshImgRq.getLayerNumber(),2));
                    imgPackData_01.append(colorLayer_01);
                    //拼接图片数据
                    tagPackData_01.append(imgPackData_01);
                    respList.add("30"+tagPackData_01);//30是类型
                    continue;
                }
                String colorLayer_02 = imageDataList.get(i);
                String data=totalNumber + currentNumber+colorLayer_02;
                respList.add("30"+data);
            }
            redisCache.deleteObject(SoketEleKey.LABLE_STATUS+refreshImgRq.getGwMac());
            redisCache.deleteObject(SoketEleKey.LABLE_RE_STATUS+refreshImgRq.getGwMac());
            String key=SoketEleKey.GW_RE_LABLE_DATA+refreshImgRq.getGwMac();
            redisCache.setCacheObject(key, JSON.toJSONString(respList),600, TimeUnit.SECONDS);
            String re_img=SoketEleKey.RE_IMG+refreshImgRq.getGwMac();
            redisCache.setCacheObject(re_img, 1,10, TimeUnit.SECONDS);
            byte[] configData= ByteUtils.hexStrToBytes(respList.get(0));
            byte[] after= InstructionByteUtils.getBYTEISData(0x5743
                    ,0x80,0x90,
                    configData,0x00);
            ByteBuf befor= InstructionByteUtils.getBFBYTEInstruction(refreshImgRq.getGwMac(),
                    (short) 128,(short)0);
            byte [] inBytes= InstructionByteUtils.getBYTEISBYTES(befor,after);
            //校验和不需要
            return SendMessage.sendMessage(inBytes,refreshImgRq.getGwMac());
        }else{
            throw  new Exception("该标签型号未找到！");
        }
    }
    //将int 变成字符串并且进行补0
    private static String convertDecimalToHexadecimal(int decimalValue,int desiredLength) {
        String hexadecimalStr = Integer.toHexString(decimalValue);
        int paddingLength = desiredLength - hexadecimalStr.length();
        if (paddingLength > 0) {
            hexadecimalStr = String.format("%0" + paddingLength + "d", 0) + hexadecimalStr;
        }
        return hexadecimalStr;
    }
    //对图片数据进行分包
    private ArrayList<String> getImgData(String imageLayer,Integer onePack){
        ArrayList<String> imageDataList=new ArrayList<>();
        int sumdata=imageLayer.length()%onePack==0?imageLayer.length()/onePack:(imageLayer.length()%onePack)+1;
        for (int i = 0; i < sumdata; i++)
        {
            if(imageLayer.length() == 0){
                break;
            }
            if(imageLayer.length() < onePack) {
                imageDataList.add(imageLayer);
                break;
            }
            imageDataList.add(imageLayer.substring(0, onePack));
            imageLayer = imageLayer.substring(onePack);
        }
        return imageDataList;
    }

}
